GBC Hardware
Specs

CPU: 8-bit (Similar to the Z80 processor.) at 4.194304 MHz for 'compatibility mode', 8.388MHz GBC Gameboy Color Mode
Main RAM: 8K Byte
Video RAM: 8K Byte
ROM: 256kBit, 512kBit, 1MBit, 2MBit and 4MBit up to 16 MBit (32kB,64kB, 128kB, 256kB, and 512kB up to 2MB)
Screen Size: 6.6 cm (2.6 inches)
Resolution: Reflective LCD at 160x144 pixels (20x18 tiles - 1 Tile being defined as 8x8 pixels)
Colour: 56 Colours at one time from 32,768 (this comes from the 8 pallettes and 4 colours for the background (8x4 = 32) and the 8 pallettes and 3 colours (since 1 of them is transparent) for the sprites (8x3 = 24) so 32 + 24 = 56).
Max # of sprites: 40
Max # sprites/line: 10
Max sprite size: 8x16
Min sprite size: 8x8
Horiz Sync: 9198 KHz (9420 KHz for SGB)
Vert Sync: 59.73 Hz (61.17 Hz for SGB)
Sound: 4 channels with stereo sound

Basic Concepts
 

Interrupts

Let's first talk about interrupts. In case you've forgotten, an interrupt is an event or signal that essentially interrupts whatever code is running (in the 209 course you guys are doing, you'll soon be talking about signals, which are just software interrupts). Interrupts are important because they can provide some sort of timing mechanism, or tell us when some hardware function has finished. For example, in our gameboy programming, we'll want to update the graphics on screen after the LCD is finished refreshing (essentially after its vertical blank). What we do is when we code our game, we define interrupt handlers to specific interrups - they are essentially functions that get called when the interrupt occurs. So, when we're in our game loop, say updating coordinate positions and the vblank interrupt occurs, our handler will be called and do its thing (i.e. redraw the sprites) and when its done we'll go right back to where we left off in our code. The good thing to note is that the gameboy has only five interrupt signals.

  1. V-Blank - This interrupt can be generated when the LCD has drawn the last line on the screen and gone into the vertical blanking period, approximately 59.7 times a second. During this period video hardware is not using video ram so it may be freely accessed.
    This period lasts approximately 1.1 milliseconds.
  2. LCDC - This interrupt can be generated by the LCD controller chip on various conditions, the most commonly used being the LYC condition, which occurs when the LCD begins to draw a certain scanline. The scanline it generates an interrupt on is selectable. (This can be used for special effects - but we probably won't be using it at all).
  3. Timer - The system timer can be set to count at specified frequencies, and will increment a count register. When this register overflows, an interrupt is generated. One of its uses is for sound playback.
  4. Serial - This interrupt occurs when a serial transfer has completed on the game link port (we'll never use this).
  5. Joypad - This interrupt occurs on a transition of any of the keypad input lines from high to low. Due to the fact that keypad "bounce"* is virtually always present, software should expect this interrupt to occur one or more times for every button press and one or more times for every button release (I'm not sure when this is used - maybe for some very sensitive gameplay I suppose. We'll be using the regular joypad function).

Graphics

The Gameboy Color doesn't use APA (all points accessable) graphics such as your computer uses. Instead it uses tiles to draw everything. While this has certain advantages, it also makes simple things such as drawing a line really difficult. The Gameboy Color uses 8x8 pixel tiles to create the background. The Gameboy Color's screen has a resolution of 20x18 tiles or 160x144 pixels. Inside its VRAM, in an area called the Background Tile Map, it stores 32x32 tiles or 256x256 pixels. So there is essentially a virtual screen of 16 extra tiles horizontally and 14 tiles vertically. This is useful for games that scroll the background. The Gameboy Color can display 256 unique tiles on the screen at one time. It has an additional VRAM bank to display an additional 256 tiles, although this kills any chance of backwards compatability with the original Gameboy. (However, it is the case that essentially all 2D games use tiles - even arcade games like Street Fighter II). Sprites are tiles independant of the background. These are used for things such as the main character and badguys. The Gameboy Color can display either 8x8 or 8x16 pixels per tile. It can display 40 sprites simultaniously. One of its main drawbacks is that it can only display 10 sprites per horizontal line. The Gameboy Color features a few hardware sprite manipulations. While it does not feature resizing the sprites or more useful things, you can flip the horizontal and vertical axis on each sprite. This is useful to make a character walk in 2 directions without needing to load a new tile into the sprite. The Gameboy Color can hold 256 8x8 pixel tiles or 128 8x16 pixel tiles into sprite ram. This is useful since it takes alot less computing power to change which ram location to display the tile than to load a unique tile into its place. Notice that there are only two layers on the GBC; the background and the window. The window is a nontransparent layer that can be applied on top of the background. It does not use its own palettes or tiles, but rather shares them with the background's. The window is useful for things such as pop-up maps, status bars that don't scroll with the background, and many other uses.

To solidify everything, let's say that Tile data is stored in VRAM and numbered 0 -127. Now a map is simply a 2D array whose entries are just the array indices of each tile to be placed on a certain area of the LCD, 0-127 in this case. So, the map area is a 32x32 byte array (1024 bytes) that makes up the Background Map, or BGMAP for short. The way the LCD draws a screen is this: it takes the byte value in the map area, and gets the corressponding tile from the tile set, and draws the 8x8 tile where it got the map byte from.

Now, the Sprite area of VRAM is divided into 40 blocks of 4-bytes (where each 4-byte block defines a sprite, thus allowing only 40 sprites on the screen at once). The 4 bytes are laid out thus

Byte 0 Y Position on Screen
Byte 1 X Position on Screen
Byte 2 Tile number
Byte 3

Flags:

BIT 7 Background Priority
BIT 6 Flip Tile Vertical
BIT 5 Flip Tile Horizontal
BIT 3 Character Bank select
BIT 0-2 Palettenumber (0-7)

ROMS

The ROMs we will compile represent a gameboy game cartridge (i.e. solid state chip that encodes data without changing). Cartridges come in varying sizes from 256kb to 16Mb (the writeable cartridge I have is 16Mb). The GBC can read these bigger cartridges through subtle trickery. What it amounts to is this; the GBC can only "see" a 256Kbit (32KByte) cartridge. This basic cartridge can be subdivided into two 16KByte pieces. The lower 16KByte piece is fixed, while the upper 16KByte piece is variable. What the gameboy does is look through a window 16KByte wide, and keeps on sliding it over to see more data. These 16KByte pieces are called banks. We can have up to 127 banks (for a 16Mbit cart). As you might have guessed, it's beneficial (rather, mandatory) that we split our code amongst these banks. Also, we have to switch to the proper bank manually, since it's not automatic.
                                         
So, we manually tell the gameboy which bank to switch to, and the gameboy in turn envokes the memory bank controller (MBC) on the cartridge. There were two major MBCs made for gb carts: MBC1 and MBC5 other minor ones were MBC2 and MBC3.

Memory Map

First of all note that the GBC uses an 8 bit CPU but its address bus in 16 bits. What this means is that it can address a whopping 64KB of memory. To be painfully precise, that means it can address 0000000000000000 to 1111111111111111, or in hexadecimal (base 16) $0000 to $FFFF (or otherwise denoted by 0x0000 to 0xFFFF). Here is a map of all of gameboy memory so you know what's going on inside.

FFFF Interrupt Enable Flag This is another I/O register, which controls the interrupts.
FF80-$FFFE Zero Page - 127 bytes Originally intended to be used as 127 bytes of stack space, this area is better suited for use as a Zero-Page, or a quick RAM access area.
$FF00-$FF7F Hardware I/O Registers This area contains all the control registers for all the hardware on the GameBoy and is basically a memory-mapped I/O area. Details on this area are below.
$FEA0-$FEFF Unusable Memory Just a small useless chunk left over. Don't expect there to be ram here.
$FE00-$FE9F OAM - Object Attribute Memory OAM is sprite RAM. This area is 40 sprites X 4 bytes long. When you with to display an object (sprite) you write 4 corresponding bytes to OAM. These 4 bytes are explained above. The tile number is taken from the Character RAM, just a BG tiles are. The X and Y locations are slightly offset (8 pixels and 16 pixels), so you can have sprites partially off of the left and top of the LCD. So if you set the location to 0,0 then the sprite would be off of the screen. To set a sprite to the top-left corner, you'd set it's location to 8,16.
$E000-$FDFF Echo RAM - Reserved, Do Not Use This area echoes internal ram, but is specified by Nintendo as reserved and shouldn't be used at all. To keep with standards and to keep compatibility, don't use this area.
$D000-$DFFF Internal RAM - Bank 1-7 (switchable - CGB only) If available.
$C000-$CFFF Internal RAM - Bank 0 (fixed) This RAM in inside the GameBoy. Generally used for most common variables and such in games.
$A000-$BFFF Cartridge RAM (If Available) If present on the cartridge, this area is mapped to the RAM on the cartridge.
$9C00-$9FFF BG Map Data 2 This area is just a second background map area like the previous one. To specify which map the video processor uses to build the background image, change the apropriate bit in the LCDC I/O register, explained later.
$9800-$9BFF BG Map Data 1 This 1024-byte long area is what the video processor uses to build the display. Each byte in this space represnts an 8x8 pixel space on the display. This area is 32x32 tiles large... EG: 1024 bytes. The display processor takes each byte and then goes into the Character RAM area and gets the corresponding tile from that area and draws it to the screen. So, if the first byte in the Map area contained $40, the display processor would get tile $40 from the Character RAM and put it in the top-left corner of the virtual screen.
$8000-$97FF Character RAM This area is RAM inside the GB unit, and is used exclusively for video purposes. This area is also known as Tile RAM, since it holds tiles. Each tile is 8x8 pixels of 2-bit color, which makes each tile 16 bytes long. This area is also divided up into two modes of tiles, signed and unsigned. In unsigned mode, tiles are numbered from 0-255 at $8000-$9000. In signed mode, tiles are numbered in two's complement from -127 to 128 at $87FF-$97FF.
$4000-$7FFF Cartridge ROM - Switchable Banks 1-xx This is where alot of your game data will exist... in this 16K space. This area is switchable or banked. You can switch in 16K chunks of the entire ROM in this area, through the use of the Memory Bank Controller (MBC) on the cartridge. How the MBC works is you basically "write" to an area in ROM, and since ROM is by nature READ ONLY MEMORY, writing a value to ROM is futile, except in the case of the MBC. It intercepts the attempted write to ROM and interprets it into a bank switch. the value you try to write to ROM is generally the bank number you want to change to.
$0150-$3FFF Cartridge ROM - Bank 0 (fixed) ROM Bank 0 is the home bank. It's the fist 16K bank of any ROM image, and is a fixed bank, which means you can't switch it out with other banks, like you can with the next section (which is discussed in the next section). When the GameBoy powers up, program execution starts at $0100, which almost always has a jump to $0150 (jp $0150), the first byte of free space. So really, $0150 will be the start of your programs. Since this bank is fixed and CANNOT be changed out, it usually contains the majority of the game's engine, or core routines.
$0100-$014F Cartridge Header Area This area in the GameBoy address space contains information about the cartridge that is inserted, including; type of cartridge, size of rom, size of ram, a Nintendo logo, and other information. Also, at $0100, there is a NOP instruction, followed by a JUMP to the start of the program, usually $0150. The GameBoy's CPU begins execution at $0100, that is why this is included. If the Nintendo logo bytes are not correct, the GameBoy will not execute the game. Upon power up, the system ROM in a GameBoy will verify that the logo is correct. Nintendo has tried to use the logo to keep only authorized developers from publishing games, since the logo is a registered trademark of Nintendo. But, a legal precedent was set in the United States in a case of Sega vs. Accolade (c.1993). Sega's Genesis console also has a signature that is a copyright of Sega, and Accolade used this logo so that their games, which were not approved by Sega, would be able to play on the Genesis console. The judge ruled in favor of Accolade, stating that using a logo to that degree was an anti competetive practice, and therefore, Accolade was allowed to continue selling their games.
$0000-$00FF Restart and Interrupt Vectors The first 255 byte area in the Gameboy address space is reserved for Interrupt Vectors and Restart Vectors. Interrupts are a break in program code generated by a piece of the hardware when a certain condition is met. These conditions can be set by the programmer. There are several different types of interrupts, and when an interrupt is generated, the program stops where it is, and jumps to one of the specified locations in the Vector Table.
I/O Registers
 

The GameBoy has instructions & registers similar to the Intel 8080, Intel 8085, & Zilog Z80 microprocessors. It has eight 8-bit general purpose registers A,B,C,D,E,F,H,L and two 16-bit registers SP & PC. Some instructions, however, allow you to use the registers A,B,C,D,E,H, & L as 16-bit registers by pairing them up in the following manner: AF,BC,DE, & HL. The PC, or Program Counter, register points to the next instruction to be executed in the GameBoy memory. The SP, or Stack Pointer, register points to the current stack position. F is the Flag Register and contains the following flags:

  • Zero Flag (Z) - This bit is set when the result of a math operation is zero or two values match when using the CP instruction.
  • Subtract Flag (N) - This bit is set if a subtraction was performed in the last math instruction.
  • Half Carry Flag (H) - This bit is set if a carry occurred from the lower nibble in the last math operation.
  • Carry Flag (C) - This bit is set if a carry occurred from the last math operation or if register A is the smaller value when executing the CP instruction.

The GBC also has, in the address range $FF00-$FF7F, memory mapped I/O registers which control all aspects of gameboy hardware: the LCD, speaker, joypad, etc.

[$FF00] ; P1
Register for reading joy pad info
and determining system type.
Bit 7 - Not used
Bit 6 - Not used
Bit 5 - P15 out port
Bit 4 - P14 out port
Bit 3 - P13 in port
Bit 2 - P12 in port
Bit 1 - P11 in port
Bit 0 - P10 in port
[$FF01] ; SB
Serial transfer data (R/W)
Don't worry about this.
[$FF02]; SC SIO control (R/W) Don't worry about this.
[$FF04]; DIV Divider Register (R/W) This register is incremented 16384 times a second. Writing any value sets it to $00.
[$FF05] = $00 ; TIMA Timer counter (R/W)
This timer is incremented by a clock frequency specified by the TAC register ($FF07). The timer generates an interrupt when it overflows.
[$FF06] = $00 ; TMA Timer Modulo (R/W)
When the TIMA overflows, this data will be loaded.
[$FF07] = $00 ; TAC Timer Control (R/W) Bit 2 - Timer Stop
0: Stop Timer
1: Start Timer

Bits 1+0 - Input Clock Select
00: 4.096 KHz
01: 262.144 KHz
10: 65.536 KHz
11: 16.384 KHz

[$FF0F]; IF
Interrupt Flag (R/W)

Bit 4: Transition from High to Low of Pin number P10-P13
Bit 3: Serial I/O transfer complete
Bit 2: Timer Overflow
Bit 1: LCDC (see STAT)
Bit 0: V-Blank

[$FF10] = $80 ; NR10 Sound Registers. Don't worry about these.
[$FF11] = $BF ; NR11
[$FF12] = $F3 ; NR12
[$FF14] = $BF ; NR14
[$FF16] = $3F ; NR21
[$FF17] = $00 ; NR22
[$FF19] = $BF ; NR24
[$FF1A] = $7F ; NR30
[$FF1B] = $FF ; NR31
[$FF1C] = $9F ; NR32
[$FF1E] = $BF ; NR33
[$FF20] = $FF ; NR41
[$FF21] = $00 ; NR42
[$FF22] = $00 ; NR43
[$FF23] = $BF ; NR30
[$FF24] = $77 ; NR50
[$FF25] = $F3 ; NR51
[$FF26] = $F1-GB; NR52
[$FF40] = $91 ; LCDC LCD Control (R/W) - value $91 at reset of GBC Bit 7 - LCD Control Operation
0: Stop completely (no picture on screen)
1: operation

Bit 6 - Window Tile Map Display Select
0: $9800-$9BFF
1: $9C00-$9FFF

Bit 5 - Window Display
0: off
1: on

Bit 4 - BG & Window Tile Data Select
0: $8800-$97FF
1: $8000-$8FFF <- Same area as OBJ

Bit 3 - BG Tile Map Display Select
0: $9800-$9BFF
1: $9C00-$9FFF

Bit 2 - OBJ (Sprite) Size
0: 8*8
1: 8*16 (width*height)

Bit 1 - OBJ (Sprite) Display
0: off
1: on

Bit 0 - BG Display
0: off
1: on

[$FF41] ; Stat LCDC Status Don't worry about this.
[$FF42] = $00 ; SCY Scroll Y (R/W) 8 Bit value $00-$FF to scroll BG Y screen
position.
[$FF43] = $00 ; SCX Scroll X (R/W) 8 Bit value $00-$FF to scroll BG X screen
position.
[$FF47] = $FC ; BGP BG & Window Palette Data (R/W) Bit 7-6 - Data for Dot Data 11 (Normally darkest color)
Bit 5-4 - Data for Dot Data 10
Bit 3-2 - Data for Dot Data 01
Bit 1-0 - Data for Dot Data 00 (Normally lightest color)
[$FF48] = $FF ; OBP0 Object Palette 0 Data (R/W) This selects the colors for sprite palette 0.
It works exactly as BGP ($FF47) except each
each value of 0 is transparent.
[$FF49] = $FF ; OBP1 Object Palette 1 Data (R/W) This Selects the colors for sprite palette 1.
It works exactly as OBP0 ($FF48).
See BGP for details.
[$FF4A] = $00 ; WY Window Y Position (R/W) 0 <= WY <= 143

WY must be greater than or equal to 0 and
must be less than or equal to 143 for
window to be visible.

[$FF4B] = $00 ; WX Window X Position (R/W) 0 <= WX <= 166

WX must be greater than or equal to 0 and
must be less than or equal to 166 for
window to be visible.

WX is offset from absolute screen coordinates
by 7. Setting the window to WX=7, WY=0 will
put the upper left corner of the window at
absolute screen coordinates 0,0.

[$FFFF] = $00 ; IE Interrupt Enable (R/W) Bit 4: Transition from High to Low of Pin
number P10-P13.
Bit 3: Serial I/O transfer complete
Bit 2: Timer Overflow
Bit 1: LCDC (see STAT)
Bit 0: V-Blank

0: disable
1: enable

Final Remarks
 

Don't be alarmed by all this information. It's mostly there just as reference. You should have mastered the ideas presented in "Basic Concepts" because these are needed to program this system. Also, you should have a general knowledge of the memory map. The I/O Register table is mostly here for completeness. However, also be aware that we need to know some of the I/O registers to properly set up windows and backgrounds (yes we can directly manipulate the registers in GBDK via ANDing and ORing bitmasks to the registers using the & and | operator). Pay special attention to the LCDC register as this is the key to controlling the LCD.

Well, this is almost all the information that defines a gameboy. It's definitely enough for us to write a game. Mostly, this information is essential to assembly programmers (and I don't think we'll be doing any ASM coding, but I could be wrong). However, if you want the technical reference document for the gameboy consult the so-called PanDoc available here. It is the de facto standard for gameboy internals. Well, that's enough of hardware. On to coding.